﻿using Abp;
using Abp.Application.Services;
using Abp.Authorization;
using Abp.IdentityFramework;
using Abp.MultiTenancy;
using Abp.Runtime.Session;
using Abp.Threading;
using ARchGL.Platform.Authorization.Roles;
using ARchGL.Platform.Authorization.Users;
using ARchGL.Platform.EntityFrameworkCore;
using ARchGL.Platform.MultiTenancy;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;

namespace ARchGL.Platform
{
    /// <summary>
    /// Derive your application services from this class.
    /// </summary>
    public abstract class PlatformAppServiceBase : ApplicationService
    {
        public TenantManager TenantManager { get; set; }

        public UserManager UserManager { get; set; }

        public IGuidGenerator GuidGenerator { get; set; }

        public RoleManager<Role> RoleManager { get; set; }

        private static ConcurrentDictionary<Type, object> TableNameDict = new ConcurrentDictionary<Type, object>();
        protected static readonly ConcurrentDictionary<string, string> CopySqlDict = new ConcurrentDictionary<string, string>();

        // private readonly IRepository<User, long> userRepository;
        protected PlatformAppServiceBase()
        {
            LocalizationSourceName = HostConsts.LocalizationSourceName;

            SequentialGuidGenerator.Instance.DatabaseType = DatabaseTypeHelper.DatabaseType;
            GuidGenerator = SequentialGuidGenerator.Instance;
        }

        protected virtual async Task<User> GetCurrentUserAsync()
        {
            var user = await UserManager.Users.Include(x => x.Roles).Where(x => x.Id == AbpSession.GetUserId()).FirstOrDefaultAsync();

            // await UserManager.FindByIdAsync(AbpSession.GetUserId().ToString());

            if (user == null)
            {
                throw new Exception("There is no current user");
            }
            return user;
        }

        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <returns></returns>
        protected virtual User GetCurrentUser()
        {
            return AsyncHelper.RunSync(GetCurrentUserAsync);
        }

        /// <summary>
        /// 验证用户是否属于指定角色
        /// </summary>
        /// <param name="roleName">角色编码（对应数据库字段为：Name）</param>
        /// <param name="userId">用户标识，为空时获取当前登录用户</param>
        /// <returns></returns>
        protected virtual bool CheckInRole(string roleName, long userId = 0)
        {
            var role = RoleManager.FindByNameAsync(roleName).Result;
            var id = userId == 0 ? AbpSession.UserId : userId;
            if (role == null || id == null) return false;

            //RoleManager.Roles

            var user = GetCurrentUser();
            var currentUserRoleList = user.Roles;
            if (currentUserRoleList == null) return false;
            return currentUserRoleList.Any(x => x.UserId == id && x.RoleId == role.Id);
        }

        /// <summary>
        /// 验证用户是否拥有特定权限
        /// </summary>
        /// <param name="permissionName">权限名称</param>
        /// <param name="userId">用户标识，为空时获取当前登录用户</param>
        /// <returns></returns>
        protected virtual async Task<bool> CheckInPermissionAsync(string permissionName, long userId = 0)
        {
            userId = userId == 0 ? AbpSession.UserId.Value : userId;
            var user = await UserManager.GetUserByIdAsync(userId);

            UserIdentifier identity = new UserIdentifier(user.TenantId, user.Id);
            if (!PermissionChecker.IsGranted(identity, permissionName))
            {
                return false;
            }
            return true;
        }

        protected virtual Task<Tenant> GetCurrentTenantAsync()
        {
            using (CurrentUnitOfWork.SetTenantId(null))
            {
                return TenantManager.GetByIdAsync(AbpSession.GetTenantId());
            }
        }

        protected virtual Tenant GetCurrentTenant()
        {
            using (CurrentUnitOfWork.SetTenantId(null))
            {
                return TenantManager.GetById(AbpSession.GetTenantId());
            }
        }

        protected virtual void CheckErrors(IdentityResult identityResult)
        {
            identityResult.CheckErrors(LocalizationManager);
        }

        /// <summary>
        /// 获取数据库表名
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        protected virtual object GetTableName<T>()
        {
            var type = typeof(T);
            if (TableNameDict.ContainsKey(type)) return TableNameDict[type];

            else
            {
                //var val = MappingConsts.Prefix + nameof(T);
                var val = type.CustomAttributes.FirstOrDefault().ConstructorArguments.FirstOrDefault().Value;
                TableNameDict.GetOrAdd(type, val);
                return val;
            }
        }
    }
}